Repository navigation
Build, test and check the libraries on their own - #2
Open
GabrielCosme wants to merge 606 commits into
Open
GabrielCosme wants to merge 606 commits into
GabrielCosme wants to merge 606 commits into
Conversation
Co-authored-by: dardengo <dardengo.cj@gmail.com>
Co-authored-by: Pedro de Santi <62271285+PedroDeSanti@users.noreply.github.com>
Co-authored-by: Pedro de Santi <62271285+PedroDeSanti@users.noreply.github.com>
Feature/new architecture
WallSensorsIndex names the wall sensors of one robot, so the robot that has them defines it. The communication README keeps the protocol; the HM-19 module, its wiring and its AT setup belong to the firmware of the board that carries them.
reference/h7 is the smallest CubeMX project that exercises every peripheral the HAL and the proxies use, derived from Micras v1's with nothing of Micras left: the internal oscillator through the PLL at 400 MHz, no main() and no callback registration. It glues the generated tree in as a consumer does, adds micras-lib with warnings as errors, and links micras_lib_bench_h7, which proves that the vendor callbacks micras-lib defines win over the weak ones and checks, on any board with the part, a storage restored across a watchdog reset, the reset cause, the timer clock against the cycle counter, the CRC unit, the FMAC and the internal reference over DMA. Its lint target covers the stm32 backend against the ARM headers. The Dockerfile generates its Cube files and adds the ARM toolchain to the host stage, the reference-h7 preset builds it from the root, and the tests' host board mirrors its pins and clock functions.
The README is the consumers' guide: how a project adds micras-lib, its options, the contracts of the stm32 and host backends, the reference project and its bench, the design of the host backend with its SPI device slot and chip models, and how to build, test, lint and document it. The Doxyfile covers the five libraries and both READMEs, and the docs target passes it the version, the theme and the output directory through the environment.
The host job builds the host preset with warnings as errors in the shared host image, runs the tests under the sanitizers, checks the formatting, lints and builds the docs, with the fetched dependencies cached. The stm32-h7 job generates the reference project's Cube files once per .ioc and Dockerfile, builds the reference and links its bench, and lints the stm32 backend. Both run on a push to any branch and on pull requests, so the restructure branch is checked before anything is merged.
STM32CubeMX writes the reference projects' .ioc files with the line endings of the platform it runs on, so without normalization a regeneration on Windows would show as a rewrite of the whole file.
FetchContent keeps the record of what it fetched under CMakeFiles/fc-stamp, and without it a restored _deps is cloned again.
The frequency fields of reference.ioc are the values STM32CubeMX 6.18.1 computes from the clock tree the file configures (HSI / 4 x 50 / 2), as it saves them. They are cached values only: the generated project is the same.
The shared stm32 sources name no chip any more. The ADC calibration, the cache, the watchdog reset flag, debug freeze and registers, the core frequency boost, the timer clock and the cycle counter are the functions of micras/hal/family.hpp, and the flash driver and its geometry are in stm32/h7, which CMake compiles for an STM32H7 board target, with the H7 behavior unchanged. The host backend implements the same functions and reads its flash geometry from the board's macros, as before.
An STM32G4 board target, such as the STM32G474 of the old Micras board, selects stm32/g4: ADC calibration with the single-ended argument only, no cache to enable, IWDG, no boost option byte, RCC_HCLK_DIV1 as the undivided APB prescaler, a cycle counter without a lock, and a page-based flash driver that programs double words into bank 2 of a 512 KB part in dual bank mode and refuses any other layout rather than erase what may be code.
scripts/check_no_chip_macros.sh fails when a conditional directive in the code every STM32 family shares (the HAL headers, stm32/src, the proxies, core, nav and comm) names a chip, a core or a peripheral only some parts have, so chip-specific code stays in the family folders CMake selects.
reference/common holds what every family's reference project runs and builds: the bench checks, the toolchain and flag setup read before project(), and the generated tree, micras-lib, bench and lint glue read after it. A family's bench.cpp only names its UART and converts the internal reference with its low-layer ADC header, and the timer check compares against the clock family::timer_clock reports, the one Pwm uses.
reference/g4 is the G4 counterpart of reference/h7: the same peripherals on the STM32G474RETx, the part of the old Micras board, at 170 MHz from the internal oscillator through the PLL, with USART3 as its UART. The Dockerfile generates its Cube files with the G4 image of STM32CubeMX, the reference-g4 preset builds it, and the CI builds, links and lints both references in one job per family, each with its generated tree cached on its .ioc and the Dockerfile.
The README names what each family needs from a consumer, above all the flash region Storage takes on each, where the family code lives and how the chip macro check keeps it there, and both reference projects with their bench.
The storage region's address follows storage_first_sector and sector_size, as on the G4, so the family header is the single source of the region the driver reads, writes and erases.
The G4 HAL flushes the flash caches at the end of every programming operation.
The rounding to double words and the check of the part's layout are facts of the family's flash, so the family header documents them; the driver's remaining file-local constants live in an anonymous namespace, which the documentation does not extract, as the host backend's do.
The family source carries no comments, so its file-local constant lives in an anonymous namespace, which the documentation does not extract, as the host backend's do.
…ard's pins Every declaration carries Doxygen: the SPI device's modes, the fields of the host SPI registers, init structure and handle, the FMAC handle states and the GPIO groups of the test board had none.
The HAL only returns the peripheral to ready from the transmission complete interrupt of the UART, which the board leaves disabled so that a reception error never aborts the circular transfer. A transfer is over once its DMA stream is, and the next one closes the state the HAL left open.
GabrielCosme
force-pushed
the
refactor/restructure
branch
from
October 4, 2026 05:49
83896a3 to
500f7ae
Compare
Their transfers are observed by polling, and the interrupt callbacks still work on a board that keeps them. The ADCs restart after an overrun or a stopped stream, a snapshot is never taken once an overrun misaligned the buffer, and the UART closes a finished DMA transfer before starting the next.
GabrielCosme
force-pushed
the
refactor/restructure
branch
from
October 4, 2026 06:28
500f7ae to
901ebd9
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The Micras libraries as their own repository:
micras_core,micras_nav,micras_comm,micras_halandmicras_proxy, with the host backend of the HAL and the SPI chip models, so other robots can build on them. The files keep their history from MicrasFirmware and micras-simulation.Consuming it
A consumer adds the repository as a submodule and defines its board target before
add_subdirectory:stm32cubemx. The HAL reads the family, H7 or G4, from its compile definitions.MICRAS_LIB_HAL_BACKEND=hostandMICRAS_LIB_CUBE_TARGET.Options (
MICRAS_LIB_NAV,_COMM,_HAL,_PROXY) leave out what a consumer does not need: a consumer of the navigation alone compiles core and nav and downloads nothing. A secondadd_subdirectoryof the repository is a no-op. The README gives the full contract.The HAL
stm32/<family>/, behind a few functions inmicras::hal::family: ADC calibration, the flash driver and its geometry, caches, the watchdog, the timer clock and the cycle counter. The shared code names no chip, andscripts/check_no_chip_macros.shenforces this in CI.References
reference/h7(STM32H725) andreference/g4(STM32G474) are the smallest CubeMX projects that use every peripheral the HAL needs, with nothing of Micras in them. Each builds and links a bench program. The bench starts only peripherals that drive no pin, so it can be flashed on any board with the part. It checks:Tests
The tests use doctest over a fake board that mirrors the references, and run under ASan and UBSan. There are 123 cases across core, comm, hal, proxy, the chip models and a first navigation suite. The navigation suite plans the ten contest mazes against recorded route times, builds the turn tables at runtime and runs the route compiler.
Standards
This repository holds the canonical copy of the files the three Micras repositories share:
.clang-format,.clang-tidy,tests/.clang-tidy, the warnings module, the clang-tidy script and the host stage of the Dockerfile. The firmware's CI checks that its copies and the simulator's are identical. The standards are GCC 15, clang-format and clang-tidy 22, CMake 3.28 to 4.4, and C++23.CI runs on every push: the host job, and one stm32 job per family.
Before merging
micras_lib_bench_h7on Micras v1 andmicras_lib_bench_g4on the old board or any STM32G474xE board. Every*_passedglobal andbench_doneshould read true. The G4 bench is the first run of the page-based flash driver.